package net.borderwars.userserver;

import net.borderwars.util.DBSession;
import net.borderwars.util.HibernateUtil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.*;
import java.text.DateFormat;
import java.text.NumberFormat;

/**
 * @author ehubbard
 *         Date: Jan 27, 2006
 *         Time: 4:05:36 PM
 */
public class Console implements Runnable {

    public Console() {
        Thread t = new Thread(this);
        t.start();
    }

    boolean done = false;

    public void run() {
        int code = 0;
        try {
            Thread.sleep(2000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        while (!done) {
            String line = null;
            try {
                System.out.print("> ");
                line = br.readLine().toLowerCase();
                if (line.startsWith("exit")) {
                    done = true;
                    code = 1;
                } else if (line.startsWith("select")) {
                    executeQuery(line);
                } else if (line.startsWith("restart")) {
                    done = true;
                    code = 0;
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
        try {
            Server.shutdown(code);
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private void executeQuery(String line) throws SQLException {
        DBSession s = HibernateUtil.getSession();
        Connection con = con = s.connection();

        PreparedStatement ps = con.prepareStatement(line);
        ResultSet rs = ps.executeQuery();
        ResultSetMetaData rmd = rs.getMetaData();
        int cid = rmd.getColumnCount();

        System.out.print("+ ");
        for (int x = 1; x <= cid; x++) {
            System.out.print(makeString('-', rmd.getColumnDisplaySize(x)) + " + ");
        }
        System.out.println();

        System.out.print("| ");
        for (int x = 1; x <= cid; x++) {
            System.out.print(getColString(rmd, x) + " | ");
        }
        System.out.print("\n");
        System.out.print("+ ");
        for (int x = 1; x <= cid; x++) {

            System.out.print(makeString('-', rmd.getColumnDisplaySize(x)) + " + ");
        }

        System.out.print("\n");

        while (rs.next()) {
            System.out.print("| ");
            for (int x = 1; x <= cid; x++) {
                System.out.print(makeDisplayableString(rs, rmd, x) + " | ");
            }
            System.out.print("\n");

        }

        System.out.print("+ ");
        for (int x = 1; x <= cid; x++) {

            System.out.print(makeString('-', rmd.getColumnDisplaySize(x)) + " + ");
        }
        System.out.println();
        s.close();
    }

    static private String makeString(char c, int x) {
        StringBuffer sb = new StringBuffer(x);
        for (int a = 0; a < x; a++) {
            sb.append(c);
        }
        return (sb.toString());
    }

    static String makeDisplayableString(ResultSet rs, ResultSetMetaData rmd, int col) throws SQLException {
        int type = rmd.getColumnType(col);
        int size = rmd.getColumnDisplaySize(col);
        String tmp;
        switch (type) {
            case java.sql.Types.BIGINT:
            case java.sql.Types.DECIMAL:
            case java.sql.Types.INTEGER:
            case java.sql.Types.NUMERIC:
            case java.sql.Types.SMALLINT:
            case java.sql.Types.TINYINT:
                tmp = NumberFormat.getNumberInstance().format(rs.getLong(col));
                break;
            case java.sql.Types.DATE:
                tmp = DateFormat.getDateInstance().format(rs.getDate(col));
                break;
            case java.sql.Types.FLOAT:
            case java.sql.Types.DOUBLE:
                tmp = NumberFormat.getNumberInstance().format(rs.getDouble(col));
                break;
            default:
                tmp = rs.getString(col);
                break;
        }
        return (padString(tmp, size));
    }

    static String getColString(ResultSetMetaData rmd, int x) throws SQLException {

        return (padString(rmd.getColumnName(x), rmd.getColumnDisplaySize(x)));
    }

    static String foramatResult(String str, int type) {
        switch (type) {
            case java.sql.Types.BIGINT:
            case java.sql.Types.DECIMAL:
            case java.sql.Types.INTEGER:
            case java.sql.Types.NUMERIC:
            case java.sql.Types.SMALLINT:
            case java.sql.Types.TINYINT:
                return (NumberFormat.getNumberInstance().format(Long.parseLong(str)));
            default:
                return (str);
        }
    }

    static String padString(String str, int size, int type) {
        return (padString(foramatResult(str, type), size));

    }

    static String padString(String str, int size) {

        if (str.length() > size) {
            return (str);
        }
        if (pads == null)
            createPads();

        String pad = pads[size - str.length()];
        return (pad + str);

    }

    static void createPads() {
        // we start with one big string.. then do substrings because then all of our
        // smaller strings will share the same udnerlying char[] array

        final int MAXPAD = 200;
        StringBuffer bigAssBuffer = new StringBuffer(MAXPAD);
        for (int x = MAXPAD; x != 0; x--) {
            bigAssBuffer.append(" ");
        }
        String bigAssString = bigAssBuffer.toString();

        pads = new String[MAXPAD];
        for (int x = 0; x < MAXPAD; x++) {
            pads[x] = bigAssString.substring(0, x);
        }

    }

    static private String[] pads = null;

}


